﻿using System;
using System.Collections.Generic;
using EnvDTE;
using Microsoft.VisualStudio.TemplateWizard;
using Microsoft.Win32;

namespace Microsoft.Services.Clab.UI.Mvvmc.VisualStudio.TemplateWizards
{
    public class MvvmcItemTemplate : IWizard
    {
        private bool canceled;

        #region IWizard Members

        public void BeforeOpeningFile(ProjectItem projectItem)
        {
        }

        public void ProjectFinishedGenerating(Project project)
        {
        }

        public void ProjectItemFinishedGenerating(ProjectItem projectItem)
        {
        }

        public void RunFinished()
        {
        }

        public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
        {
            if (replacementsDictionary == null)
                throw new ArgumentNullException("replacementsDictionary");

            var window = new MvvmcItemTemplateWindow();

            window.Prefix = replacementsDictionary["$rootname$"];
            window.ControllerLogicalName = replacementsDictionary["$rootname$"];

            window.BaseClassesSets = new Dictionary<string, string[]>()
            {
                {"ClabMvvmc/Code/Wpf", new [] { "Microsoft.Services.Clab.UI.Mvvmc.CodeControllerBase, Microsoft.Services.Clab.UI.Mvvmc", "Microsoft.Services.Clab.UI.Mvvmc.Presentation.WpfViewModelBase, Microsoft.Services.Clab.UI.Mvvmc.Presentation", "Microsoft.Services.Clab.UI.Mvvmc.Presentation.WpfViewBase, Microsoft.Services.Clab.UI.Mvvmc.Presentation" } },
                {"ClabMvvmc/Code/Silverlight",new [] { "Microsoft.Services.Clab.UI.Mvvmc.CodeControllerBase, Microsoft.Services.Clab.UI.Mvvmc","Microsoft.Services.Clab.UI.Mvvmc.Presentation.SilverlightViewModelBase, Microsoft.Services.Clab.UI.Mvvmc.Presentation","Microsoft.Services.Clab.UI.Mvvmc.Presentation.SilverlightContentControlViewBase, Microsoft.Services.Clab.UI.Mvvmc.Presentation" } },
                {"ClabMvvmc/Workflow/Wpf", new[] { "Microsoft.Services.Clab.UI.Mvvmc.Activities.WorkflowControllerBase","Microsoft.Services.Clab.UI.Mvvmc.Presentation.WpfViewModelBase","Microsoft.Services.Clab.UI.Mvvmc.Presentation.WpfViewBase" } }
            };

            this.LoadAdditionalBaseClassesSetFromRegistry(window.BaseClassesSets);

            window.SelectedBaseClassesSet = replacementsDictionary["$wizarddata$"];

            if (window.ShowDialog().GetValueOrDefault())
            {
                replacementsDictionary["$rootname$"] = window.Prefix;
                replacementsDictionary.Add("$controllername$", window.ControllerName);
                replacementsDictionary.Add("$viewmodelname$", window.ViewModelName);
                replacementsDictionary.Add("$viewname$", window.ViewName);
                replacementsDictionary.Add("$controllerlogicalname$", window.ControllerLogicalName);
                replacementsDictionary.Add("$controllerbasetype$", GetTypeFullName(window.ControllerBaseTypeAssemblyQualifiedName));
                replacementsDictionary.Add("$viewmodelbasetype$", GetTypeFullName(window.ViewModelBaseTypeAssemblyQualifiedName));
                replacementsDictionary.Add("$viewbasetypename$", GetTypeName(window.ViewBaseTypeAssemblyQualifiedName));
                replacementsDictionary.Add("$viewbasetypenamespace$", GetTypeNamespace(window.ViewBaseTypeAssemblyQualifiedName));
                replacementsDictionary.Add("$viewbasetypeassembly$", GetAssemblyName(window.ViewBaseTypeAssemblyQualifiedName));
            }
            else
            {
                canceled = true;
            }
        }

        private void LoadAdditionalBaseClassesSetFromRegistry(Dictionary<string, string[]> dictionary)
        {
            try
            {
                var regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft Services\Clab\Mvvmc\VisualStudio\TemplateBaseClassesSets");
                if (regKey != null)
                {
                    foreach (var valueName in regKey.GetValueNames())
                    {
                        dictionary.Add(valueName, regKey.GetValue(valueName) as string[]);
                    }
                }
            }
            catch (Exception)
            {
            }
        }

        public bool ShouldAddProjectItem(string filePath)
        {
            return !canceled;
        }

        #endregion

        #region Private methods

        private static string GetTypeFullName(string typeAssemblyQualifiedName)
        {
            if (typeAssemblyQualifiedName == null)
            {
                throw new ArgumentNullException("typeAssemblyQualifiedName");
            }

            return typeAssemblyQualifiedName.Split(',')[0];
        }

        private static string GetTypeName(string typeAssemblyQualifiedName)
        {
            if (typeAssemblyQualifiedName == null)
            {
                throw new ArgumentNullException("typeAssemblyQualifiedName");
            }

            var typeFullName = typeAssemblyQualifiedName.Split(',')[0];

            var pos = typeFullName.LastIndexOf('.');
            if (pos > 0)
            {
                return typeFullName.Substring(pos + 1).Trim();
            }
            else
            {
                return typeFullName.Trim();
            }
        }

        private static string GetTypeNamespace(string typeAssemblyQualifiedName)
        {
            if (typeAssemblyQualifiedName == null)
            {
                throw new ArgumentNullException("typeAssemblyQualifiedName");
            }

            var typeFullName = typeAssemblyQualifiedName.Split(',')[0];

            var pos = typeFullName.LastIndexOf('.');
            if (pos > 0)
            {
                return typeFullName.Substring(0, pos).Trim();
            }
            else
            {
                return string.Empty;
            }
        }

        private static string GetAssemblyName(string typeAssemblyQualifiedName)
        {
            if (typeAssemblyQualifiedName == null)
            {
                throw new ArgumentNullException("typeAssemblyQualifiedName");
            }

            var typeNameParts = typeAssemblyQualifiedName.Split(',');
            if (typeNameParts.Length > 1)
            {
                return typeNameParts[1].Trim();
            }
            else
            {
                return string.Empty;
            }
        }

        #endregion
    }
}
